// Using the ProjectBuilderService example:
// -------------------------------
// bool isClean = VisualStudioPrjBuilderService.VisualStudioPrjClean(@"D:\desktop\DTEtest");
// string? err = VisualStudioPrjBuilderService.VisualStudioPrjBuild(@"D:\desktop\DTEtest", "DTEtest");
// err = VisualStudioPrjBuilderService.VisualStudioPrjLaunch(@"D:\desktop\DTEtest", "DTEtest");
// isClean = VisualStudioPrjBuilderService.VisualStudioPrjClean(@"D:\desktop\DTEtest");
using System.Xml.Linq;
using MultiAgentsShared;

namespace MultiAgentsClient.Tools;

public class VisualStudioPrjBuilderService
{
    public VisualStudioPrjBuilderService()
    {
    }

    //[GptFunc("Builds the specified .NET project by invoking the 'dotnet build' command. " +
    //"Automatically appends the '.csproj' extension if not present in the project name. " +
    //"Returns a string message indicating whether the build succeeded, failed, or if the project file was not found.",
    //    typeof(ClientToolSetConfig))]
    public string VisualStudioPrjBuild(
    [GptFuncParam("the root path of the project directory, without the project file name or extension")]
    string rootPath,
    [GptFuncParam("the name of the project file without the '.csproj' extension; the extension is appended automatically if omitted")]
    string projectName)
    {
        if (!projectName.EndsWith(".csproj"))
        {
            projectName += ".csproj";
        }
        string projectPath = Path.Combine(rootPath, projectName);
        if (!File.Exists(projectPath))
        {
            return $"Project file not found: {projectPath}";
        }

        var command = $"build \"{projectPath}\"";
        CmdResult buildResult = CmdToolProvider.ExecuteCommand("dotnet", command);

        string errorAndOutput = $"output:\n{buildResult.Output}\nerrors:\n{buildResult.Error}";

        return buildResult.ExitCode == 0 ? "Build succeeded." : (string.IsNullOrEmpty(buildResult.Output) && string.IsNullOrEmpty(buildResult.Error)) ? "Build failed with unknown error." : errorAndOutput;
    }

    //[GptFunc("Launches a built .NET executable file. " +
    //"If the project name is provided, it constructs the executable file path based on the project directory and name; " +
    //"otherwise, it attempts to launch the executable directly from the provided full path. " +
    //"Returns a string message indicating the outcome of the launch attempt, including success, failure, or an error message if the executable file could not be found.",
    //    typeof(ClientToolSetConfig))]
    public string VisualStudioPrjLaunch(
    [GptFuncParam("the full path to the executable file or the root directory of the project if a project name is provided")]
    string projectPath,
    [GptFuncParam("optional: the name of the project without the '.exe' extension; if provided, used with the projectPath to construct the path to the executable")]
    string? projectName = null)
    {
        var filePath = projectName == null ? projectPath : ConstructExePath(projectPath, projectName);

        if (filePath == null)
        {
            return "Failed to find the path of the executable file. Please use the full path";
        }

        CmdResult launchResult = CmdToolProvider.ExecuteCommand(filePath, "");

        string errorAndOutput = $"output:\n{launchResult.Output}\nerrors:\n{launchResult.Error}";

        return launchResult.ExitCode == 0 ? "Launch succeeded." : (string.IsNullOrEmpty(launchResult.Output) && string.IsNullOrEmpty(launchResult.Error)) ? "Launch failed with unknown error." : errorAndOutput;
    }

    //[GptFunc("Cleans the build output of the specified .NET project by invoking the 'dotnet clean' command. " +
    //"This removes the build output from the default output directory. " +
    //"Returns a boolean indicating whether the clean operation succeeded.",
    //    typeof(ClientToolSetConfig))]
    public bool VisualStudioPrjClean(
    [GptFuncParam("the full path of the project directory or the project file (.csproj) to clean.")]
    string projectPath)
    {
        if (!File.Exists(projectPath) && !Directory.Exists(projectPath))
        {
            return false;
        }

        var command = $"clean \"{projectPath}\"";
        CmdResult cleanResult = CmdToolProvider.ExecuteCommand("dotnet", command);

        return cleanResult.ExitCode == 0;
    }

    private static string? ConstructExePath(string projectDirectory, string projectName)
    {
        string projectFilePath = Path.Combine(projectDirectory, $"{projectName}.csproj");

        if (!File.Exists(projectFilePath))
        {
            return null;
        }

        XDocument projectFile = XDocument.Load(projectFilePath);

        string? targetFramework = projectFile.Element("Project")?.Element("PropertyGroup")?.Element("TargetFramework")?.Value;

        if (string.IsNullOrEmpty(targetFramework))
        {
            return null;
        }

        string basePath = Path.Combine(projectDirectory, "bin", "Debug", targetFramework);
        string exePath = Path.Combine(basePath, $"{projectName}.exe");

        if (File.Exists(exePath))
        {
            return exePath;
        }

        basePath = Path.Combine(projectDirectory, "bin", "Release", targetFramework);
        exePath = Path.Combine(basePath, $"{projectName}.exe");

        if (File.Exists(exePath))
        {
            return exePath;
        }

        return null;
    }
}
